package com.gemantic.task.handler;

import java.util.Date;

import org.springframework.lang.NonNull;

import com.gemantic.task.dto.ResResult;
import com.gemantic.task.dto.TaskContext;

/**
 * @author daishun
 * @since 2019/8/26
 */
public interface ITaskHandler<T> {

    /**
     * 处理器名字
     *
     * @param context 当前任务
     * @return String
     */
    String getHandlerName(TaskContext context);

    /**
     * 核心处理函数，包含在事物中。
     *
     * @param processData requestData 对象，已经呗转换为对象
     * @param context     当前task上下文
     * @return 执行结果，ResResult
     */

    @NonNull
    ResResult process(T processData, TaskContext context);

    /**
     * 异常处理，当在beforeProcess,process执行中有异常抛出后，就会调用该函数。
     *
     * @param context 当前任务上下文
     * @param ex      待处理的异常
     * @return null/ResResult 对异常的处理结果。该结果就是task的执行结果。
     */
    ResResult handleException(TaskContext context, Exception ex);

    /**
     * 需要重试时，计算下次执行时间
     *
     * @param context 当前任务的上下文
     * @param result  当前任务的执行结果
     * @return 下次任务执行的时间点
     */
    @NonNull
    Date getNextRunTime(TaskContext context, ResResult result);

    /**
     * 当前任务处理完成后，会调用afterProcess,去释放资源。
     *
     * @param context 当前任务上下文
     * @return null/ResResult 返回值不会影响当前task的结果，但会影响task链的执行结果
     */
    ResResult afterProcess(TaskContext context);

    /**
     * taskhandler 准备阶段，调用beforeProcess时，未开启事物。
     *
     * @param processData 待处理的参数
     * @param context     当前任务上下文
     * @return ResResult：该task已经有明确结果，不需要继续处理。null：继续处理。
     */
    ResResult beforeProcess(T processData, TaskContext context);

    /**
     * 预估当前任务会执行多长时间，用于锁定任务。短任务2分钟（默认），长任务（30分钟)
     *
     * @return 分钟数
     */
    int estimateRunMinutes();


    /**
     * 延迟任务执行
     *
     * @param data    推迟任务执行
     * @param context
     * @return
     */
    ResResult needPostpone(T data, TaskContext context);

    /**
     * 超出最大执行次数后
     *
     * @param data    task参数
     * @param context task上下文
     * @return 结果
     */
    ResResult afterMaxRetryTimes(T data, TaskContext context);

    /**
     * 超出最大执行时间
     *
     * @param data    task参数
     * @param context task上下文
     * @return 结果
     */
    ResResult afterMaxRunTime(T data, TaskContext context);

    /**
     * 获取任务最大运行时间,单位秒,比如24*3600表示最大执行时间为24小时
     *
     * @param data 请求参数
     * @return 最大执行时间
     */
    int getMaxRunTime(T data);

}
